package cn.edu.sjtu.stap.cfg.internal;

import java.util.*;
import cn.edu.sjtu.stap.sdg.internal.*;

public aspect BuildTiming {
    public pointcut mainMethodPc() : call(* writeInterModuleCfg(..));

    public pointcut buildIntraCfgPc() : call(* buildIntraModuleCfg(..));
    
    public pointcut buildIntraSdgPc() : call(* buildIntraSdg(..));
    
    public pointcut buildSdgPc() : call(* buildInterSdg(..));

    public pointcut buildInterCfgPc() : call(* buildInterModuleCfg(..));

    public pointcut buildHgPc() : call(* buildHierarchyGraph(..));

    public pointcut buildCgPc() : call(* buildCallGraph(..));

    private long intraTime = 0;

    private long interTime = 0;
    
    private long interSdgTime = 0;

    private long hgTime = 0;

    private long cgTime = 0;

    private Stack<Long> time = new Stack<Long>();

    private void recordStartTime() {
        long t = System.currentTimeMillis();
        time.push(t);
    }

    private long getInterval() {
        long endTime = System.currentTimeMillis();
        long startTime = time.pop();

        return endTime - startTime;
    }

    before() : buildIntraCfgPc() {
        recordStartTime();
    }

    after() : buildIntraCfgPc() {
        intraTime += getInterval();
    }
    

    before() : buildInterCfgPc() {
        recordStartTime();
    }

    after() : buildInterCfgPc() {
        interTime += getInterval();
    }

    before() : buildHgPc() {
        recordStartTime();
    }

    after() : buildHgPc() {
        hgTime += getInterval();
    }

    before() : buildCgPc() {
        recordStartTime();
    }

    after() : buildCgPc() {
        cgTime += getInterval();
    }

    after() : mainMethodPc() {
        try {
            Initializer.out.writeLine("");
            Initializer.out.writeLine("Time for building each graph: ");
            Initializer.out.writeLine("Intra-Module Control Flow Graph: " + intraTime + " ms.");
            Initializer.out.writeLine("Hierarchy Graph: " + hgTime + " ms.");
            Initializer.out.writeLine("Call Graph: " + cgTime + " ms.");
            Initializer.out.writeLine("Inter-Module Control Flow Graph: " + interTime + " ms.");
           // Initializer.out.writeLine("Inter-Procedural System Dependence Graph: " + interSdgTime + " ms.");
            Initializer.out.writeLine("Total Time: " + (intraTime + hgTime + cgTime + interTime) + " ms.");
        } catch (Exception e) {
            System.err.println("Error writing time!");
            e.printStackTrace();
        }
    }
}
